package verify

import (
	"fmt"
	"github.com/gin-gonic/gin/binding"
	"log"
	"reflect"
	"strings"

	"github.com/go-playground/locales/en"
	"github.com/go-playground/locales/zh"
	ut "github.com/go-playground/universal-translator"
	"github.com/go-playground/validator/v10"
	enTranslator "github.com/go-playground/validator/v10/translations/en"
	zhTranslator "github.com/go-playground/validator/v10/translations/zh"
)

// 定义一个全局翻译器T
var translator ut.Translator

//全局校验器
var validate *validator.Validate

// initValidator 修改gin框架中的Validator引擎属性，实现自定制
func initValidator() {
	if v ,ok := binding.Validator.Engine().(*validator.Validate); ok {
		validate = v
	}
}

// initTrans 初始化全局 translator
func initTrans(locale string) (err error) {
	zhT := zh.New() // 中文翻译器
	enT := en.New() // 英文翻译器

	// 第一个参数是备用（fallback）的语言环境
	// 后面的参数是应该支持的语言环境（支持多个）
	// uni := ut.New(zhT, zhT) 也是可以的
	uni := ut.New(enT, zhT, enT)

	// locale 通常取决于 http 请求头的 'Accept-Language'
	var ok bool
	// 也可以使用 uni.FindTranslator(...) 传入多个locale进行查找
	translator, ok = uni.GetTranslator(locale)
	if !ok {
		return fmt.Errorf("uni.GetTranslator(%s) failed", locale)
	}

	// 注册翻译器
	switch locale {
	case "en":
		err = enTranslator.RegisterDefaultTranslations(validate, translator)
	case "zh":
		err = zhTranslator.RegisterDefaultTranslations(validate, translator)
	default:
		err = enTranslator.RegisterDefaultTranslations(validate, translator)
	}
	return
}

// registerJsonTag 自定义错误信息字段，获取 json tag 作为响应字段
func registerJsonTag() {
	validate.RegisterTagNameFunc(func(fld reflect.StructField) string {
		name := strings.SplitN(fld.Tag.Get("json"), ",", 2)[0]
		if name == "-" {
			return ""
		}
		return name
	})
}

// removeTopStruct 祛除结构体前缀
func removeTopStruct(fields map[string]string) map[string]string {
	res := map[string]string{}
	for field, err := range fields {
		res[field[strings.LastIndex(field, ".")+1:]] = err
	}
	return res
}

// GetValidError 将校验的错误 汉化 + 去前缀
func GetValidError(err validator.ValidationErrors) map[string]string {
	return removeTopStruct(err.Translate(translator)) // err 使用翻译器翻译错误
}

// InitValidator 初始化翻译器，在 gin 启动的时候执行
// locale: zh
func InitValidator() {
	initValidator()
	if err := initTrans("zh"); err != nil { // 翻译器
		log.Fatalf("init transator failed. error: %v", err)
	}
	registerJsonTag()
	registerAdminRequestValidation()  // admin 注册
	registerListAdminValidation()  // list admin

	registerUserRequestValidation()  // user register
	regTagPhone()
	regUniquePhone()
}

func V() *validator.Validate {
	return validate
}

func T()ut.Translator{
	return translator
}
